#ifndef RXE_POLL_H
#define RXE_POLL_H

#define RXE_POOL_ALIGN (16)

enum rxe_pool_flags {
    RXE_POOL_ATOMIC = BIT(0),
    RXE_POOL_INDEX = BIT(1),
    RXE_POOL_KEY = BIT(2),
    RXE_POOL_NO_ALLOC = BIT(4),
};

/*pool里面的元素类型，如mr,pd,qp等*/
enum rxe_elem_type {
    RXE_TYPE_UC,
    RXE_TYPE_PD,
    RXE_TYPE_AH,
    RXE_TYPE_SRQ,
    RXE_TYPE_QP,
    RXE_TYPE_CQ,
    RXE_TYPE_MR,
    RXE_TYPE_MW,
    RXE_TYPE_MC_GRP,
    RXE_TYPE_MC_ELEM,
    RXE_NUM_TYPES, /* keep me last */
};

struct rxe_pool_entry;

struct rxe_type_info {
    const char *name;
    size_t size;
    size_t elem_offset;
    void (*cleanup)(struct rxe_pool_entry *obj);
    enum rxe_pool_flags flags;
    u32 max_index, min_index;
    size_t key_offset, key_size;
};

/*这个结构体相当于一个节点，其它结构体想充当节点需要包含这个结构体*/
struct rxe_pool_entry {
    //通过它找到对应的根节点
    struct rxe_pool *pool;
    struct kref ref_cnt; //https://blog.csdn.net/youzhangjing_/article/details/124257420
    struct list_head list;
    /* only used if keyed */
    struct rb_node key_node;
    /* only used if indexed */
    struct rb_node index_node;
    u32 index;
};

/*相当于一个根节点*/
struct rxe_pool {
    struct rxe_dev *rxe;
    /* protects pool add/del/search */
    rwlock_t pool_lock;
    size_t elem_size;
    void (*cleanup)(struct rxe_pool_entry *obj);
    enum rxe_pool_flags flags;
    enum rxe_elem_type type;
    unsigned int max_elem;
    atomic_t num_elem;
    /* only used if indexed */
    struct {
        struct rb_root tree;
        unsigned long *table;
        size_t table_size;
        u32 last;
        u32 max_index;
        u32 min_index;
    } index;
    /* only used if keyed */
    struct {
        struct rb_root tree;
        size_t key_offset;
        size_t key_size;
    } key;
};

/*函数声明*/
int rxe_pool_init(struct rxe_dev *rxe, struct rxe_pool *pool,
        enum rxe_elem_type type, u32 max_elem);
void rxe_pool_cleanup(struct rxe_pool *pool);
void *rxe_alloc_locked(struct rxe_pool *pool);
void *rxe_alloc(struct rxe_pool *pool);
int __rxe_add_to_pool(struct rxe_pool *pool, struct rxe_pool_entry *elem);
int __rxe_add_index_locked(struct rxe_pool_entry *elem);
int __rxe_add_index(struct rxe_pool_entry *elem);
void __rxe_drop_index_locked(struct rxe_pool_entry *elem);
void __rxe_drop_index(struct rxe_pool_entry *elem);
int __rxe_add_key_locked(struct rxe_pool_entry *elem, void *key);
int __rxe_add_key(struct rxe_pool_entry *elem, void *key);
void *rxe_pool_get_index_locked(struct rxe_pool *pool, u32 index);
void *rxe_pool_get_index(struct rxe_pool *pool, u32 index);
void *rxe_pool_get_key_locked(struct rxe_pool *pool, void *key);
void *rxe_pool_get_key(struct rxe_pool *pool, void *key);
void rxe_elem_release(struct kref *kref);
void __rxe_drop_key_locked(struct rxe_pool_entry *elem);
void __rxe_drop_key(struct rxe_pool_entry *elem);

/*宏定义--供外部调用*/
#define rxe_add_to_pool(pool, obj) __rxe_add_to_pool(pool, &(obj)->pelem)
#define rxe_add_index_locked(obj) __rxe_add_index_locked(&(obj)->pelem)
#define rxe_add_index(obj) __rxe_add_index(&(obj)->pelem)
#define rxe_drop_index_locked(obj) __rxe_drop_index_locked(&(obj)->pelem)
#define rxe_drop_index(obj) __rxe_drop_index(&(obj)->pelem)
#define rxe_add_key_locked(obj, key) __rxe_add_key_locked(&(obj)->pelem, key)
#define rxe_add_key(obj, key) __rxe_add_key(&(obj)->pelem, key)
#define rxe_drop_key_locked(obj) __rxe_drop_key_locked(&(obj)->pelem)
#define rxe_drop_key(obj) __rxe_drop_key(&(obj)->pelem)
#define rxe_add_ref(elem) kref_get(&(elem)->pelem.ref_cnt)
#define rxe_drop_ref(elem) kref_put(&(elem)->pelem.ref_cnt, rxe_elem_release)

#endif
